import { WeaLocaleProvider } from "ecCom";
import _ from 'lodash';
import { comsType, unitWidthProp } from "../../../../constants/form";
import utils from '../../../../utils';
import './index.less';
import validates from '../../../common/validates';
import {
  isBrowserHrm,
  isHiddenInput,
  isText,
  isTelephone,
  isMobileCom,
  isEmail
} from './typeof';

const getLabel = WeaLocaleProvider.getLabel;
const formatMultiLang = WeaLocaleProvider.formatMultiLang;
const { FORM_HEADER, FORM_FOOTER, FOOTER } = comsType;


let customComs = null;
const get = (name, handle = null) => {
  return type => {
    let Com;

    type = type.replace(/_/g, '-').toLowerCase();

    if (customComs && customComs[type]) {
      return customComs[type][name] || handle;
    }

    try {
      Com = require(`./${type}/${name}`).default;
    } catch(error) {
      Com = handle;
    }

    return Com;
  }
}
const getValidate = get('validate', {});
const getTransfer = get('transfer');

export const getDesign = get('Design');
export const getView = get('View');
export const getProps = get('Props');
export const getDefaultData = get('data', {});

/**
 * 注册自定义组件
 * @param {*} name 组件名称
 * @param {*} com 组件对象 { View, Props, validate... } 
 */
export const register = (name, com) => {
  if (!customComs) {
    customComs = {};
  }

  if (_.isObject(name)) {
    customComs = {
      ...customComs,
      ...name
    };
  } else {
    customComs[name] = com;
  }
};

export const getViewableComponent = com => {
  const isInFormBody = ![FORM_HEADER, FORM_FOOTER,FOOTER].includes(com.type);
  const isNotSubComponent = !com.pid;

  return isNotSubComponent && isInFormBody;
};

const propsCfgToViewCfg = (type, propsCfg) => {
  const transfer = getTransfer(type);

  if (!transfer) return propsCfg;

  let viewCfg = propsCfg;

  if (transfer.toViewData) {
    viewCfg = {
      ...propsCfg,
      ...transfer.toViewData(propsCfg),
    };
  }

  return viewCfg;
};

// 组件props配置 转成view配置
export const propsComToViewCom = component => {
  const com = { ...component };
  const defaultRule = { validate: '', error: () => '' };
  const { required, min, max, title, hidden, validateTypes } = com.config;
  const { required: vRequired = defaultRule, limit = { validate: () => true, error: () => '' }, custom } = getValidate(com.type);

  com.rules = [];
  com.name = title;
  com.visible = true; // 用于控制组件显隐，如字段显示规则

  if (required == 1) {
    com.rules.push({
      validate: vRequired.validate || (({ value }) => {
        // 兼容String和空数组
        return undefined !== value && !!String(value).trim();
      }),
      error: ({ config, name }) => {
        const { labelTitleID } = config;
        const tips = labelTitleID ? getLabel(labelTitleID, name) : formatMultiLang(name);
        
        return `${getLabel('502542', '请填写')} ${tips}`;
      }
    });
  }

  if (hidden && hidden == 1) { //隐藏字段不做渲染
    com.visible = false;
  }

  if (min && min.value || max && max.value) {
    com.rules.push(limit);
  }

  if (custom) {
    com.rules.push(custom);
  }

  if(validateTypes && validateTypes.length > 0) {
    validateTypes.forEach(type => com.rules.push(validates[type]))
  }

  com.config = propsCfgToViewCfg(com.type, com.config);

  if ('defaultValue' in com.config && !isBrowserHrm(com)) {

    if (isText(com) || isTelephone(com)) {
      com.config.defaultValue = com.config.defaultValue.slice(0, 100);
    } 

    if (isHiddenInput(com)) {
      com.config.defaultValue = com.config.defaultValue.slice(0, 50);
    }
    
    if (isTelephone(com) && !/^[0-9|-]*$/.test(com.config.defaultValue)) {
      com.config.defaultValue = '';
    } 
    
    if (isMobileCom(com) && !/^1\d{10}$/.test(com.config.defaultValue)) {
      com.config.defaultValue = '';
    }

    if (isEmail(com) && !/^[a-zA-Z0-9._-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(com.config.defaultValue)) {
      com.config.defaultValue = '';
    }

    com.value = com.config.defaultValue;
  }

  return com;
}

export { propsCfgToViewCfg };

export const generateSubComponents = com => {
  const type = com.type.toLowerCase();
  const { split } = getTransfer(type);

  return split(com);
};

export const smoothWidths = {
  forReduce: widths => {
    const len = widths.length;

    if (!len) return [];

    if (1 === len) return [1];
    if (2 === len) return [1 / 2, 1 / 2];
    if (3 === len) return [unitWidthProp, unitWidthProp, unitWidthProp];
    
    return widths;
  },
  forAdd: (widths, index, replace = true) => {
    const width = widths.toString();
    
    if (!width) return [1];

    if (1 == width) return [1 / 2, 1 / 2];

    if (_.isEqual(widths, [1 / 2, 1 / 2])) {
      return Array(3).fill(1 / 3);
    }

    if (widths.length - 1 >= index) {
      if (replace) {
        widths[index] = unitWidthProp;
      } else {
        widths = utils.addItem(widths, unitWidthProp, index)
      }
    } else {
      widths.push(unitWidthProp);
    }

    return widths;
  }
};

export const recalculateWidths = (widths) => {
  const total = utils.reduce(widths);
  const radito = 1 / total;

  if(total > 1) return widths;
  
  return widths.map(width => width * radito);
  
}